﻿using Memcached.ClientLibrary;
using Janus.Cores.Configuration;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Janus.Cores.Cacheing
{
    public class MemCachedHelper
    {
        private static readonly MemcachedClient mc = new MemcachedClient();
        static MemCachedHelper()
        {
            Init();
        }
        public static void Init()
        {
            List<string> serverlist = new List<string>();//服务器可以是多个:"192.168.1.11:11211", "192.168.1.12:11211", "192.168.1.13:11211"
            List<int> weights = new List<int>();

            MemCacheConfigSection config = (MemCacheConfigSection)ConfigurationManager.GetSection("memcached");
            if (config == null)
            {
                throw new InvalidCastException("无法获取有效的memcached配置节");
            }
            foreach (ServerElement s in config.Servers)
            {
                serverlist.Add(s.ToString());
                weights.Add(s.Weight);
            }

            //初始化池  
            SockIOPool pool = SockIOPool.GetInstance();
            pool.SetServers(serverlist.ToArray());//设置连接池可用的cache服务器列表，server的构成形式是IP:PORT（如：127.0.0.1:11211
            pool.SetWeights(weights.ToArray());
            pool.InitConnections = config.MemConfig.InitConnections;// 3;//初始连接数  
            pool.MinConnections = config.MemConfig.MinConnections;//3;//最小连接数  
            pool.MaxConnections = config.MemConfig.MaxConnections;//5;//最大连接数  
            pool.SocketConnectTimeout = config.MemConfig.SocketConnectTimeout;//1000;//设置连接的套接字超时  
            pool.SocketTimeout = config.MemConfig.SocketTimeout;//3000;//设置套接字超时读取  
            pool.MaintenanceSleep = config.MemConfig.MaintenanceSleep;// 30;//设置维护线程运行的睡眠时间。如果设置为0，那么维护线程将不会启动,30就是每隔30秒醒来一次  

            //获取或设置池的故障标志。  
            //如果这个标志被设置为true则socket连接失败，将试图从另一台服务器返回一个套接字如果存在的话。  
            //如果设置为false，则得到一个套接字如果存在的话。否则返回NULL，如果它无法连接到请求的服务器。  
            pool.Failover = config.MemConfig.Failover;//true;
            pool.Nagle = config.MemConfig.Nagle;//false;//如果为false，对所有创建的套接字关闭Nagle的算法  
            pool.Initialize();
        }
        /// <summary>
        /// 获得客户端实例  
        /// </summary>
        public static MemcachedClient Instance
        {
            get
            {
                //MemcachedClient mc = new MemcachedClient();
                mc.EnableCompression = false;
                return mc;
            }
        }

        public static SockIOPool SockIOPool
        {
            get
            {
                return SockIOPool.GetInstance();
            }
        }
        public void Dispose()
        {
            var instance = SockIOPool.GetInstance();
            if (instance != null)
            {
                instance.Shutdown();
            }
        }

        #region 内部方法
        public static bool Add(string key, object value)
        {
            return Instance.Add(key, value);
        }

        public static bool Add(string key, object value, DateTime expiry)
        {
            return Instance.Add(key, value, expiry);
        }

        public static bool Add(string key, object value, int hashCode)
        {
            return Instance.Add(key, value, hashCode);
        }

        public bool Add(string key, object value, DateTime expiry, int hashCode)
        {
            return Instance.Add(key, value, expiry, hashCode);
        }

        public static long Decrement(string key)
        {
            return Instance.Decrement(key);
        }

        public static long Decrement(string key, long inc)
        {
            return Instance.Decrement(key, inc);
        }

        public static long Decrement(string key, long inc, int hashCode)
        {
            return Instance.Decrement(key, inc, hashCode);
        }

        public static bool Delete(string key)
        {
            return Instance.Delete(key);
        }

        public static bool Delete(string key, DateTime expiry)
        {
            return Instance.Delete(key, expiry);
        }

        public static bool Delete(string key, object hashCode, DateTime expiry)
        {
            return Instance.Delete(key, hashCode, expiry);
        }

        public static bool FlushAll()
        {
            return Instance.FlushAll();
        }

        public static bool FlushAll(ArrayList servers)
        {
            return Instance.FlushAll(servers);
        }

        public static object Get(string key)
        {
            return Instance.Get(key, null, false);
        }

        public static object Get(string key, int hashCode)
        {
            return Instance.Get(key, (int)hashCode, false);
        }

        public static object Get(string key, object hashCode, bool asString)
        {
            return Instance.Get(key, hashCode, asString);
        }

        public static long GetCounter(string key)
        {
            return Instance.GetCounter(key, null);
        }

        public static long GetCounter(string key, object hashCode)
        {
            return Instance.GetCounter(key, hashCode);
        }

        public static Hashtable GetMultiple(string[] keys)
        {
            return Instance.GetMultiple(keys, null, false);
        }

        public static Hashtable GetMultiple(string[] keys, int[] hashCodes)
        {
            return Instance.GetMultiple(keys, hashCodes, false);
        }

        public static Hashtable GetMultiple(string[] keys, int[] hashCodes, bool asString)
        {
            return Instance.GetMultiple(keys, hashCodes, asString);
        }

        public static object[] GetMultipleArray(string[] keys)
        {
            return Instance.GetMultipleArray(keys, null, false);
        }

        public static object[] GetMultipleArray(string[] keys, int[] hashCodes)
        {
            return Instance.GetMultipleArray(keys, hashCodes, false);
        }

        public static object[] GetMultipleArray(string[] keys, int[] hashCodes, bool asString)
        {
            return Instance.GetMultipleArray(keys, hashCodes, asString);
        }

        public static long Increment(string key)
        {
            return Instance.Increment(key);
        }

        public static long Increment(string key, long inc)
        {
            return Instance.Increment(key, inc);
        }

        public static long Increment(string key, long inc, int hashCode)
        {
            return Instance.Increment(key, inc, hashCode);
        }

        public static bool KeyExists(string key)
        {
            return Instance.KeyExists(key);
        }

        public static bool Replace(string key, object value)
        {
            return Instance.Replace(key, value);
        }

        public static bool Replace(string key, object value, DateTime expiry)
        {
            return Instance.Replace(key, value, expiry);
        }

        public static bool Replace(string key, object value, int hashCode)
        {
            return Instance.Replace(key, value, hashCode);
        }

        public static bool Replace(string key, object value, DateTime expiry, int hashCode)
        {
            return Instance.Replace(key, value, expiry, hashCode);
        }

        public static bool Set(string key, object value)
        {
            return Instance.Set(key, key);
        }

        public static bool Set(string key, object value, DateTime expiry)
        {
            return Instance.Set(key, key, expiry);
        }

        public static bool Set(string key, object value, int hashCode)
        {
            return Instance.Set(key, key, hashCode);
        }

        public static bool Set(string key, object value, DateTime expiry, int hashCode)
        {
            return Instance.Set(key, key, expiry, hashCode);
        }

        public static Hashtable Stats()
        {
            return Instance.Stats(null);
        }

        public static Hashtable Stats(ArrayList servers)
        {
            return Instance.Stats(servers);
        }

        public static bool StoreCounter(string key, long counter)
        {
            return Instance.Set(key, counter);
        }

        public static bool StoreCounter(string key, long counter, int hashCode)
        {
            return Instance.Set(key, counter, hashCode);
        }

        public static long CompressionThreshold
        {
            get
            {
                return Instance.CompressionThreshold;
            }
            set
            {
                Instance.CompressionThreshold = value;
            }
        }

        public static string DefaultEncoding
        {
            get
            {
                return Instance.DefaultEncoding;
            }
            set
            {
                Instance.DefaultEncoding = value;
            }
        }

        public static bool EnableCompression
        {
            get
            {
                return Instance.EnableCompression;
            }
            set
            {
                Instance.EnableCompression = value;
            }
        }

        public static string PoolName
        {
            get
            {
                return Instance.PoolName;
            }
            set
            {
                Instance.PoolName = value;
            }
        }

        public static bool PrimitiveAsString
        {
            get
            {
                return Instance.PrimitiveAsString;
            }
            set
            {
                Instance.PrimitiveAsString = value;
            }
        }
        #endregion
    }
}
